package org.webdb.mysql;

import org.apache.log4j.Logger;
import org.spawndb.DBManagerFactory;
import org.spawndb.ISpawnDBManager;
import org.spawndb.util.ScriptRunner;
import org.webdb.WebContextListener;

import javax.servlet.ServletContextEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

public class MYSQLManagerFactory extends WebContextListener {


    private static ISpawnDBManager dbManager;
    private static String dbUser="root";
    private static String dbPwd="";
    private static String dbPort=null;
    private static String dbName="mysqlapptest";
  


    private static Logger log = Logger.getLogger("org.webdb.mysql.MYSQLManagerFactory");

    private void startup(){
        if(getParameter("db.user")!=null) dbUser = getParameter("db.user");
        if(getParameter("db.password")!=null) dbPwd = getParameter("db.password");
        if(getParameter("db.port")!=null) dbPort = getParameter("db.port");

        Map<String,String> options = new HashMap<String,String>();
        if(dbPort!=null)
            options.put("port", dbPort);
        if(dbUser!=null){
            options.put("initialize-user", "true");
            options.put("initialize-user.user", dbUser);
            options.put("initialize-user.password", dbPwd);
        }
        String dbManagerClassName = "org.spawndb.impl.mysql.MYSQLManager";
        try {
            dbManager= DBManagerFactory.forClass(dbManagerClassName);
            if(getParameter("db.base.dir")!=null){
                String basedir = getParameter("db.base.dir").trim();
                dbManager.setBaseDir(basedir+"/db/mysql");
            }
            dbManager.setDBProperties(options);
            dbManager.start();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("DB initialization failed",e);
        }
    }

    private void initDB() throws SQLException, IOException {
        Connection conn=null;
        Statement st=null;
        String conString ="jdbc:mysql://localhost";
        if(dbPort!=null) conString += ":"+dbPort;
        PrintWriter writer = getLogWriter();
        try{
            conn = DriverManager.getConnection(conString,dbUser,dbPwd);
            ScriptRunner runner = new ScriptRunner(conn, false, true,writer);
            String scriptsDir = getParameter("context.home")+"/conf/";
            runner.runScript(new BufferedReader(new FileReader(scriptsDir+"/init.sql")));
        }
        finally{
            if(st!=null) st.close();
            if(conn!=null)conn.close();
        }
    }

    private PrintWriter getLogWriter(){
        File logDir = new File(getParameter("context.home"),"logs");
        logDir.mkdirs();
        File logFile = new File(logDir,"initdb.log");
        logFile.delete();
        PrintWriter writer=null;        
        try{
            logFile.createNewFile();
            writer = new PrintWriter(logFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return writer;
    }

    private boolean dbExists() throws Exception {
        if(getParameter("db.name")!=null)
            dbName = getParameter("db.name");
        File db = new File(dbManager.getDataDir(),dbName);
        return db.exists();
    }

    public void contextInitialized(ServletContextEvent sce) {
        super.contextInitialized(sce);
        startup();
        try {
            if(!dbExists())
                initDB();
        } catch (Exception e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }


    public void contextDestroyed(ServletContextEvent sce) {
        super.contextDestroyed(sce);
        try {
            dbManager.stop();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("DB stopping failed",e);
         }
    }

    public static ISpawnDBManager getMYSMysqlManager(){
        return dbManager;
    }


}